/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package simhya.matheval;
import org.sbml.jsbml.ASTNode;
import simhya.matheval.function.*;
/**
 *
 * @author Luca
 */
public class DynamicFunctionNode extends FunctionNode {

    public DynamicFunctionNode(FunctionDefinition function, int numberOfChildren) {
        super(function,numberOfChildren);
    }

    @Override
    public boolean canBeConvertedToNumericalExpression() {
        return function.canBeConvertedToNumericalFunction();
    }

    @Override
    public ExpressionNode convertToNumericalExpression(Evaluator eval) {
        FunctionDefinition f = function.convertToNumericalFunction(eval);
        ExpressionNode n = new DynamicFunctionNode(f,numberOfChildren);
        for (int i=0;i<numberOfChildren;i++)
            n.addChild(children[i]);
        n = eval.checkNodeDefinition(n);
        return n;
    }



   

   @Override
    void computeValue() {
        double[] arguments = new double[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeValue();
            arguments[i] = children[i].value;
        }
        super.value = function.compute(arguments);
    }

    @Override
    void computeValue(SymbolArray varReference) {
        double[] arguments = new double[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeValue(varReference);
            arguments[i] = children[i].value;
        }
        super.value = function.compute(arguments);
    }

    @Override
    void computeValue(int evaluationCode) {
        double[] arguments = new double[super.numberOfChildren];
        if (random || super.evaluationCode != evaluationCode) {
            super.evaluationCode = evaluationCode;
            for (int i=0;i<super.numberOfChildren;i++) {
                children[i].computeValue(evaluationCode);
                arguments[i] = children[i].value;
            }
            super.value = function.compute(arguments);
        }
    }

    @Override
    void computeValue(SymbolArray varReference, int evaluationCode) {
        double[] arguments = new double[super.numberOfChildren];
        if (random || super.evaluationCode != evaluationCode) {
            super.evaluationCode = evaluationCode;
            for (int i=0;i<super.numberOfChildren;i++) {
                children[i].computeValue(varReference,evaluationCode);
                arguments[i] = children[i].value;
            }
            super.value = function.compute(arguments);
        }
    }

    @Override
    void computeValueLocal(SymbolArray localVariables) {
        double[] arguments = new double[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeValueLocal(localVariables);
            arguments[i] = children[i].value;
        }
        super.value = function.compute(arguments);
    }

    @Override
    void computeValueLocal(SymbolArray localVariables, SymbolArray globalVariables) {
        double[] arguments = new double[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeValueLocal(localVariables,globalVariables);
            arguments[i] = children[i].value;
        }
        super.value = function.compute(arguments);
    }

    @Override
    void computeValueLocal(SymbolArray localVariables, int evaluationCode) {
        double[] arguments = new double[super.numberOfChildren];
        if (random || super.evaluationCode != evaluationCode) {
            super.evaluationCode = evaluationCode;
            for (int i=0;i<super.numberOfChildren;i++) {
                children[i].computeValueLocal(localVariables,evaluationCode);
                arguments[i] = children[i].value;
            }
            super.value = function.compute(arguments);
        }
    }

    @Override
    void computeValueLocal(SymbolArray localVariables, SymbolArray globalVariables, int evaluationCode) {
        double[] arguments = new double[super.numberOfChildren];
        if (random || super.evaluationCode != evaluationCode) {
            super.evaluationCode = evaluationCode;
            for (int i=0;i<super.numberOfChildren;i++) {
                children[i].computeValueLocal(localVariables,globalVariables,evaluationCode);
                arguments[i] = children[i].value;
            }
            super.value = function.compute(arguments);
        }
    }
    
    

    @Override
    public boolean isLogicalExpression() {
        return super.function.isLogicalFunction();
    }


    @Override
    protected Object clone() throws CloneNotSupportedException {
        DynamicFunctionNode newNode = new DynamicFunctionNode(this.function,this.numberOfChildren);
        this.copyContent(newNode);
        return newNode;
    }

    @Override
    ASTNode convertToJSBML() {
        throw new UnsupportedOperationException("MATHML conversion of user defined functions is not supported");
    }
    
    @Override
    void computeContinuousChangeStatus() {
        boolean[] arguments = new boolean[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeContinuousChangeStatus();
            arguments[i] = children[i].canChangeContinuously;
        }
        super.canChangeContinuously = function.computeContinuousChangeStatus(arguments);
    }

    @Override
    void computeContinuousChangeStatus(SymbolArray varReference) {
        boolean[] arguments = new boolean[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeContinuousChangeStatus(varReference);
            arguments[i] = children[i].canChangeContinuously;
        }
        super.canChangeContinuously = function.computeContinuousChangeStatus(arguments);
    }

    @Override
    void computeContinuousChangeStatusLocal(SymbolArray localVariables) {
        boolean[] arguments = new boolean[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeContinuousChangeStatusLocal(localVariables);
            arguments[i] = children[i].canChangeContinuously;
        }
        super.canChangeContinuously = function.computeContinuousChangeStatus(arguments);
    }

    @Override
    void computeContinuousChangeStatusLocal(SymbolArray localVariables, SymbolArray globalVariables) {
        boolean[] arguments = new boolean[super.numberOfChildren];
        for (int i=0;i<super.numberOfChildren;i++) {
            children[i].computeContinuousChangeStatusLocal(localVariables,globalVariables);
            arguments[i] = children[i].canChangeContinuously;
        }
        super.canChangeContinuously = function.computeContinuousChangeStatus(arguments);
    }

    
    
    
    

}
